package com.admin.interfaces.web;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import com.admin.application.OrderService;
import com.admin.application.PlayService;
import com.admin.conts.SessionKeys;
import com.admin.domain.modle.AjaxResponse;
import com.admin.domain.modle.Member;
import com.admin.domain.modle.OrderSeat;
import com.admin.domain.modle.Play;
import com.admin.infrastructure.RemoteDataUtil;
import com.admin.utils.HaiyinException;
import com.admin.utils.OrderStatus;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.XmlResult;
import com.foxinmy.weixin4j.payment.WeixinPayProxy;
import com.foxinmy.weixin4j.payment.mch.MchPayRequest;
import com.foxinmy.weixin4j.payment.mch.Order;
import com.foxinmy.weixin4j.util.Consts;
import com.foxinmy.weixin4j.util.IOUtil;
import com.foxinmy.weixin4j.util.ObjectId;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer;
import com.foxinmy.weixin4j.xml.XmlStream;

@Controller
@RequestMapping("/wechat")
public class WechatController extends BaseController {
    private final Logger log = LoggerFactory.getLogger(WechatController.class);
    @Autowired
    private WeixinPayProxy weixinPayProxy;
    @Autowired
    private OrderService orderService;
    @Autowired
    private PlayService playService;

    @ResponseBody
    @RequestMapping(value = "/precheck", method = RequestMethod.POST)
    public AjaxResponse precheck(@RequestBody com.admin.domain.modle.Order order) {
        //,@CookieValue("userId") String userId
        Play play = playService.get(order.getPlayId());
        if (play == null) {
            return AjaxResponse.error("演出不能为空");
        }
        if (StringUtils.isBlank(order.getPlayDate())) {
            return AjaxResponse.error("演出日期不能为空");
        }
        List<OrderSeat> seats = order.getSeats();
        if (CollectionUtils.isEmpty(seats)) {
            return AjaxResponse.error("选座不能为空");
        }
        Member member = (Member) getSession().getAttribute(SessionKeys.OAUTH_USER_KEY);
        if (member == null) {
            return AjaxResponse.error("登陆超时，请刷新页面。");
        }
        int[] ids = new int[seats.size()];
        OrderSeat os = null;
        for (int i = 0; i < seats.size(); i++) {
            os = seats.get(i);
            if (os.getSeatId() == null || StringUtils.isBlank(os.getName()) || os.getPrice() <= 0d) {
                return AjaxResponse.error("选座信息有误");
            }
            ids[i] = os.getSeatId().intValue();
        }
        try {
            int orderId = RemoteDataUtil.postHaiyinOrderCheck(order.getId(), order.getPlayId(), order.getPlayDate(),
                    ids);
            if(-1 == orderId){
                return AjaxResponse.error("该座位已被锁定，请选其他座位");
            }
            order.setOrderId(orderId);
            order.setPlayName(play.getName());
            order.setPlayCode(play.getCode());
            order.setPlayImage(play.getUrl());
            order.setOpenId(member.getOpenId());
            order.setNickName(member.getNickName());
            order.setStatus(OrderStatus.PRE.name());
            if(StringUtils.isNotEmpty(order.getUserId())){
                order.setUserId(order.getUserId());
            }
            orderService.preCreate(order);
            return AjaxResponse.success(orderId);
        } catch (HaiyinException e) {
            return AjaxResponse.error(e.getMessage());
        } catch (Exception e) {
            log.error("precheck error", e);
            return AjaxResponse.error("系统繁忙,请稍后再试precheck");
        }
    }

    @RequestMapping(value = "/order/{id}", method = RequestMethod.GET)
    public String order(Model model, @PathVariable("id") Integer orderId) {
        com.admin.domain.modle.Order order = orderToModel(model, orderId);
        if (!order.getStatus().equals(OrderStatus.PRE.name())) {
            return "redirect:/wechat/payment/" + orderId;
        }
        return "wap/order";
    }

    private com.admin.domain.modle.Order orderToModel(Model model, Integer orderId) {
        com.admin.domain.modle.Order order = orderService.findById(orderId);
        model.addAttribute("order", order);
        return order;
    }

    @RequestMapping(value = "/payment/{id}", method = RequestMethod.GET)
    public String payment(Model model, @PathVariable("id") Integer orderId) {
        orderToModel(model, orderId);
        return "wap/order_detail";
    }

    /**
     * 发起支付
     *
     * @return MchPayRequest
     */
    @ResponseBody
    @RequestMapping("/pay")
    public AjaxResponse pay(@RequestParam(name = "orderId") Integer orderId,
            @RequestParam(name = "uname", required = false) String uname,
            @RequestParam(name = "phone", required = false) String phone) {
        Member member = (Member) getSession().getAttribute(SessionKeys.OAUTH_USER_KEY);
        if (member == null) {
            return AjaxResponse.error("登陆超时，请刷新页面。");
        }
        com.admin.domain.modle.Order order = orderService.findById(orderId);
        if (order == null) {
            return AjaxResponse.error("订单不存在");
        }
        if (OrderStatus.valueOf(order.getStatus()).ordinal() > 1) {
            return AjaxResponse.error("订单状态有误");
        }

        String openId = member.getOpenId(); // 微信ID
        String body = String.format("购买「%s」", order.getPlayName());// 支付描述
        String tradeNo = ObjectId.get().toHexString(); // 订单号
        double totalFee = order.getPayAmount(); // 订单金额
        String notifyUrl = String.format("%s%s", getRootLocation(), "/wechat/paynotify"); // 回调地址
        String createIp = getIpAddr(); // 客户端地址
        String attach = orderId.toString(); // 附加信息
        if(StringUtils.isNotEmpty(uname) && StringUtils.isNotEmpty(uname))
        orderService.postCreate(orderId, tradeNo, uname, phone);

        try {
            MchPayRequest payRequest = weixinPayProxy.createJSPayRequest(openId, body, tradeNo, totalFee, notifyUrl,
                    createIp, attach);
            return AjaxResponse.success(payRequest.toRequestObject());
        } catch (WeixinException e) {
            log.error("微信支付异常", e);
            return AjaxResponse.error("系统繁忙，请稍后再试pay");
        } catch (HaiyinException e) {
            log.error("wechat pay", e);
            return AjaxResponse.error(e.getMessage());
        }
    }

    @RequestMapping(value = "/paynotify", method = RequestMethod.POST)
    @ResponseBody
    public String payNotify(InputStream input) throws IOException {
        // 获取订单信息
        String content = StringUtil.newStringUtf8(IOUtil.toByteArray(input));
        Order order = ListsuffixResultDeserializer.deserialize(content, Order.class);
        log.info("jsapi_notify_order_info{}:", order);
        // 验证签名
        String sign = order.getSign();
        String valid_sign = weixinPayProxy.getWeixinSignature().sign(order);
        log.info("微信签名----->sign={},vaild_sign={}", sign, valid_sign);
        if (!sign.equals(valid_sign)) {
            return XmlStream.toXML(new XmlResult(Consts.FAIL, "签名错误"));
        }
        orderService.postPayment(order);
        return XmlStream.toXML(new XmlResult(Consts.SUCCESS, ""));
    }

    @ResponseBody
    @RequestMapping("/cancelOrder")
    public AjaxResponse cancelOrder(@RequestParam(name = "orderId") Integer orderId) {
        com.admin.domain.modle.Order order = orderService.findById(orderId);
        if (order == null) {
            return AjaxResponse.error("订单不存在");
        }
        OrderStatus os = OrderStatus.valueOf(order.getStatus());
        if (os.ordinal() > 2) {
            return AjaxResponse.error("订单状态有误");
        }
        try {
            orderService.cancelOrder(orderId);
        } catch (HaiyinException e) {
            log.error("cancel order fail", e);
            return AjaxResponse.error(e.getMessage());
        }
        return AjaxResponse.success();
    }
    
    @ResponseBody
    @RequestMapping("/deleteOrder")
    public AjaxResponse deleteOrder(@RequestParam(name = "orderId") Integer orderId) {
        com.admin.domain.modle.Order order = orderService.findById(orderId);
        if (order == null) {
            return AjaxResponse.error("订单不存在");
        }
        OrderStatus os = OrderStatus.valueOf(order.getStatus());
        if (os != OrderStatus.VERIFIED) {
            return AjaxResponse.error("订单状态有误");
        }
        try {
            orderService.deleteOrder(orderId);
        } catch (HaiyinException e) {
            log.error("delete order fail", e);
            return AjaxResponse.error(e.getMessage());
        }
        return AjaxResponse.success();
    }
}
